Матч
412, Запрещенные строки (ForbiddenStrings)
Дивизион 1,
Уровень 1
Строка, состоящая из букв A, B и
C, называется запрещенной, если в ней встречаются три подряд буквы, одна из
которых A, другая B, а третья C. Например, строка BAACAACCBAAA
является запрещенной, в то время как AABBCCAABB – нет.
Вычислить количество
незапрещенных строк длины n.
Класс: ForbiddenStrings
Метод: long
countNotForbidden(int n)
Ограничения: 1 £ n £ 30.
Вход. Длина строк n.
Выход. Количество незапрещенных строк длины n.
Пример входа
n |
2 |
3 |
4 |
Пример выхода
9
21
51
РЕШЕНИЕ
динамическое программирование
Занесем в rep[i] количество незапрещенных строк длины i, у которых две последние буквы
одинаковы. В ячейке nonrep[i] будем
хранить число незапрещенных строк длины i,
у которых две последние буквы разные. Ответом на задачу будет значение rep[n] + nonrep[n].
Вычислим непосредственно значения
ячеек:
rep[1] = 0, rep[2] = 3 (AA, BB, CC),
nonrep[1] = 3 (A, B, C), nonrep[2] = 6 (AB,
AC, BA, BC, CA, CB)
Вычисление rep[i]. На место i - ой
буквы необходимо ставить ту же букву, которая стоит на (i – 1) - ом месте.
rep[i] = rep[i – 1] + nonrep[i – 1]
Вычисление nonrep[i]. Если (i – 1) -
ая и (i – 2) - ая буквы одинаковы, то на i - ое место можно поставить любую из
двух букв, не совпадающую с ней. Если (i
– 1) - ая и (i – 2) - ая буквы разные, то (i – 1) - ую букву продублировать в качестве i - ой нельзя, нельзя поставить на i - ое место букву, отличную от (i – 1) - ой и (i –
2) - ой. Поэтому в этом случае на i - ое место следует ставить (i – 2) - ую букву.
nonrep[i] =
2 * rep[i – 1] + nonrep[i – 1]
Например, ячейки массивов rep и nonrep
будут содержать следующие значения:
i |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
rep[i] |
0 |
0 |
3 |
9 |
21 |
51 |
123 |
297 |
nonrep[i] |
0 |
3 |
6 |
12 |
30 |
72 |
174 |
420 |
ПРОГРАММА
#include <cstdio>
#include <vector>
using namespace std;
long long rep[31], nonrep[31];
class ForbiddenStrings
{
public:
long long
countNotForbidden(int n)
{
int i;
rep[1] = 0; rep[2]
= 3;
nonrep[1] = 3;
nonrep[2] = 6;
for(i = 3; i <= n; i++)
{
rep[i] = rep[i-1] + nonrep[i-1];
nonrep[i] = 2 *
rep[i-1] + nonrep[i-1];
}
return rep[n] + nonrep[n];
}
};